package cc.autoapi.pucong.liteflow.design;

import cc.autoapi.pucong.liteflow.design.core.configuration.AuthorizationInterceptor;
import cc.autoapi.pucong.liteflow.design.core.configuration.DefaultAuthorizationInterceptor;
import cc.autoapi.pucong.liteflow.design.core.configuration.LiteFlowDesignConfiguration;
import cc.autoapi.pucong.liteflow.design.core.properties.LiteFlowDesignProperties;
import cc.autoapi.pucong.liteflow.design.core.properties.SecurityConfig;
import cc.autoapi.pucong.liteflow.design.service.DesignService;
import cc.autoapi.pucong.liteflow.design.service.DesignServiceImpl;
import com.yomahub.liteflow.core.FlowExecutor;
import com.yomahub.liteflow.springboot.LiteflowProperty;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.ObjectProvider;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.annotation.Resource;

@Configuration
@ComponentScan("cc.autoapi.pucong.liteflow.design")
@ConditionalOnClass({RequestMappingHandlerMapping.class})
@EnableConfigurationProperties(LiteFlowDesignProperties.class)
public class LiteFlowDesignAutoConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(LiteFlowDesignAutoConfiguration.class);

    private final LiteFlowDesignProperties properties;

    private final ObjectProvider<DesignService> designServiceProvider;

    private final ObjectProvider<AuthorizationInterceptor> authorizationInterceptorProvider;

    private final Environment environment;

    private final ApplicationContext applicationContext;
    @Resource
    private FlowExecutor flowExecutor;

    @Autowired
    private LiteflowProperty liteflowProperty;

    @Value("${server.servlet.context-path}")
    private String systemPath;

    @Value("${server.port}")
    private Integer systemPort;

    public LiteFlowDesignAutoConfiguration(LiteFlowDesignProperties liteFlowDesignProperties,
                                           ObjectProvider<DesignService> designService,
                                           ObjectProvider<AuthorizationInterceptor> authorizationInterceptor,
                                           Environment environment,
                                           ApplicationContext applicationContext) {
        this.properties = liteFlowDesignProperties;
        this.designServiceProvider = designService;
        this.authorizationInterceptorProvider = authorizationInterceptor;
        this.environment = environment;
        this.applicationContext = applicationContext;
    }

    @Bean
    @ConditionalOnMissingBean
    public LiteFlowDesignConfiguration liteFlowDesignConfiguration() {
        LiteFlowDesignConfiguration configuration = new LiteFlowDesignConfiguration();
        // 数据源操作
        configuration.setDesignService(designServiceProvider.getIfAvailable(this::createDesignService));
        // 鉴权操作
        configuration.setAuthorizationInterceptor(authorizationInterceptorProvider.getIfAvailable(this::createAuthorizationInterceptor));
        // 是否需要登录
        configuration.setRequireLogin(properties.getRequireLogin());
        // 登录过期时间
        configuration.setLoginExpire(properties.getLoginExpire());
        // 是否启用设计器
        configuration.setEnable(properties.isEnable());
        // 设计器访问地址，可以自定义
        configuration.setWeb(properties.getWeb());
        // 是否只读
        configuration.setReadonly(properties.getReadonly());
        // 是否启用跨域支持
        configuration.setSupportCrossDomain(properties.isSupportCrossDomain());

        // 打印banner
        if (this.properties.isBanner() && configuration.isEnable()) {
            configuration.printBanner(systemPath, systemPort);
        }
        return configuration;
    }

    public DesignService createDesignService() {
        return new DesignServiceImpl(liteflowProperty, properties, authorizationInterceptorProvider.getIfAvailable(this::createAuthorizationInterceptor), flowExecutor);
    }

    public AuthorizationInterceptor createAuthorizationInterceptor() {
        SecurityConfig securityConfig = properties.getSecurityConfig();
        AuthorizationInterceptor authorizationInterceptor = new DefaultAuthorizationInterceptor(properties.getRequireLogin(), properties.getReadonly(), properties.isEnable(), securityConfig.getUsername(), securityConfig.getPassword());
        return authorizationInterceptor;
    }

}
